package com.luobr.backend.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.luobr.backend.constant.UserConstant;
import com.luobr.backend.common.ResponseCode;
import com.luobr.backend.exception.BusinessException;
import com.luobr.backend.exception.ThrowUtils;
import com.luobr.backend.manage.auth.StpKit;
import com.luobr.backend.model.dto.user.UserAddRequest;
import com.luobr.backend.model.dto.user.UserQueryRequest;
import com.luobr.backend.model.entity.User;
import com.luobr.backend.model.vo.user.UserLoginVO;
import com.luobr.backend.model.vo.user.UserQueryVO;
import com.luobr.backend.service.UserService;
import com.luobr.backend.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.List;
import java.util.stream.Collectors;

import static com.luobr.backend.constant.UserConstant.USER_LOGIN_STATE;


/**
 * @author 罗念笙
 * @description 针对表【user(用户)】的数据库操作Service实现
 * @createDate 2025-02-19 22:10:03
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Override
    public long registerUser(String userAccount, String userPassword, String checkPassword) {
        // 参数校验
        ThrowUtils.throwIf(ObjUtil.hasEmpty(userAccount, userPassword, checkPassword), ResponseCode.PARAMS_ERROR, "传入参数为空！");
        ThrowUtils.throwIf(!userPassword.equals(checkPassword), ResponseCode.PARAMS_ERROR, "密码和确认密码不相同！");
        // 检验账户是否重复
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userAccount", userAccount);
        ThrowUtils.throwIf(this.baseMapper.selectCount(queryWrapper) > 0, ResponseCode.PARAMS_ERROR, "该账户已经存在！");
        // 保存用户信息
        User user = new User();
        user.setUserName(UserConstant.DEFAULT_USERNAME);
        user.setUserRole(UserConstant.USER_ROLE.USER);
        user.setUserAccount(userAccount);
        user.setUserPassword(getEncryptPassword(userPassword));
        ThrowUtils.throwIf(!this.save(user), ResponseCode.OPERATION_ERROR, "该账户已经存在！");
        return user.getId();
    }


    @Override
    public UserLoginVO loginUser(String userAccount, String userPassword, HttpServletRequest request) {
        // 参数校验
        ThrowUtils.throwIf(ObjUtil.hasEmpty(userAccount, userPassword), ResponseCode.PARAMS_ERROR, "传入参数为空！");
        // 查询用户信息
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userAccount", userAccount);
        queryWrapper.eq("userPassword", getEncryptPassword(userPassword));
        List<User> users = this.baseMapper.selectList(queryWrapper);
        ThrowUtils.throwIf(CollectionUtil.isEmpty(users) || users.size() > 1, ResponseCode.PARAMS_ERROR, "账号或者密码输入错误！");
        User user = users.get(0);
        // 保存用户的登录状态
        request.getSession().setAttribute(USER_LOGIN_STATE, user);
        // 返回用户参数
        return UserLoginVO.objToLoginVo(user);
    }

    @Override
    public UserLoginVO getLoginUser(HttpServletRequest request) {
        // 1、获取用户登录信息
        Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE);
        ThrowUtils.throwIf(userObj == null, ResponseCode.NOT_LOGIN_ERROR);
        // 2、查询数据库，保证唯一性
        User user = this.getById(((User) userObj).getId());
        ThrowUtils.throwIf(user == null, ResponseCode.NOT_LOGIN_ERROR);
        // 3. 记录用户的登录态
        request.getSession().setAttribute(USER_LOGIN_STATE, user);
        // 4. 记录用户登录态到 Sa-token，便于空间鉴权时使用，注意保证该用户信息与 SpringSession 中的信息过期时间一致
        StpKit.SPACE.login(user.getId());
        StpKit.SPACE.getSession().set(USER_LOGIN_STATE, user);
        // 返回脱敏后的用户信息
        return UserLoginVO.objToLoginVo(user);
    }

    @Override
    public Boolean logoutUser(HttpServletRequest request) {
        // 获取用户登录信息
        HttpSession session = request.getSession();
        Object userObj = session.getAttribute(USER_LOGIN_STATE);
        ThrowUtils.throwIf(userObj == null, ResponseCode.NOT_LOGIN_ERROR);
        // 移除缓存里的登录信息
        session.removeAttribute(USER_LOGIN_STATE);
        return true;
    }

    @Override
    public Long addUser(UserAddRequest userAddRequest) {
        User user = new User();
        BeanUtils.copyProperties(userAddRequest, user);
        // 校验用户是否已经存在相同的账号
        QueryWrapper<User> condition = new QueryWrapper<User>().eq("userAccount", user.getUserAccount());
        ThrowUtils.throwIf(this.baseMapper.selectOne(condition) != null, ResponseCode.PARAMS_ERROR, "该账户已经存在！");
        // 新增用户使用默认密码
        user.setUserPassword(getEncryptPassword(UserConstant.DEFAULT_PASSWORD));
        ThrowUtils.throwIf(!save(user), ResponseCode.OPERATION_ERROR);
        return user.getId();
    }

    @Override
    public String getEncryptPassword(String password) {
        return DigestUtils.md5DigestAsHex((UserConstant.SALE + password).getBytes());
    }

    @Override
    public QueryWrapper<User> getQueryWrapper(UserQueryRequest userQueryRequest) {
        if (userQueryRequest == null) {
            throw new BusinessException(ResponseCode.PARAMS_ERROR, "请求参数为空");
        }
        // 获取到所有传参
        Long id = userQueryRequest.getId();
        String userAccount = userQueryRequest.getUserAccount();
        String userName = userQueryRequest.getUserName();
        String userProfile = userQueryRequest.getUserProfile();
        String userRole = userQueryRequest.getUserRole();
        String sortField = userQueryRequest.getSortField();
        String sortOrder = userQueryRequest.getSortOrder();

        // 拼接查询条件
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(ObjUtil.isNotNull(id), "id", id);
        queryWrapper.eq(StrUtil.isNotBlank(userRole), "userRole", userRole);
        queryWrapper.like(StrUtil.isNotBlank(userAccount), "userAccount", userAccount);
        queryWrapper.like(StrUtil.isNotBlank(userName), "userName", userName);
        queryWrapper.like(StrUtil.isNotBlank(userProfile), "userProfile", userProfile);
        queryWrapper.orderBy(StrUtil.isNotEmpty(sortField), sortOrder.equals("ascend"), sortField);
        return queryWrapper;
    }

    @Override
    public Page<UserQueryVO> getUserQueryVOPage(UserQueryRequest userQueryRequest) {
        // 获取分页条件
        int current = userQueryRequest.getCurrent();
        int pageSize = userQueryRequest.getPageSize();
        // 查询到分页数据
        Page<User> userPage = this.page(new Page<>(current, pageSize), this.getQueryWrapper(userQueryRequest));
        List<User> userList = userPage.getRecords();
        // 返回脱敏后分页数据
        Page<UserQueryVO> UserQueryVOPage = new Page<>(current, pageSize, userPage.getTotal());
        if (CollUtil.isEmpty(userList)) {
            return UserQueryVOPage;
        }
        // 将分页数据封装成脱敏后分页数据
        List<UserQueryVO> UserQueryVOList = userList.stream().map(UserQueryVO::objToQueryVo).collect(Collectors.toList());
        UserQueryVOPage.setRecords(UserQueryVOList);
        return UserQueryVOPage;
    }
}




